﻿/** EasyWeb spa v3.1.8 date:2020-05-04 License By http://easyweb.vip */
layui.define(["layer", "setter", "layRouter"], function (exports) {

    var jquery = layui.jquery;
    var layer = layui.layer;
    var setter = layui.setter;
    var layRouter = layui.layRouter;
    var layuiBody = ".layui-layout-admin>.layui-body";
    var layuiTab = layuiBody + ">.layui-tab";
    var e = ".layui-layout-admin>.layui-side>.layui-side-scroll";
    var j = ".layui-layout-admin>.layui-header";
    var c = "admin-side-nav";
    var admin = {version: "3.1.8", layerData: {}};

    /**
     * 折叠/展开侧导航
     * @param expand true和false
     */
    admin.flexible = function (expand) {
        var r = jquery(".layui-layout-admin");
        var q = r.hasClass("admin-nav-mini");
        if (expand === undefined) {
            expand = q
        }
        if (q === expand) {
            if (expand) {
                admin.hideTableScrollBar();
                r.removeClass("admin-nav-mini")
            } else {
                r.addClass("admin-nav-mini")
            }
            // 触发admin模块的flexible({*})事件
            layui.event.call(this, "admin", "flexible({*})", {expand: expand});
            admin.resizeTable(600)
        }
    };

    /**
     * 设置侧导航栏选中
     * @param url 无需#前缀
     */
    admin.activeNav = function (url) {
        if (!url) {
            url = location.hash
        }
        if (!url) {
            return console.warn("active url is null")
        }
        jquery(e + ">.layui-nav .layui-nav-item .layui-nav-child dd.layui-this").removeClass("layui-this");
        jquery(e + ">.layui-nav .layui-nav-item.layui-this").removeClass("layui-this");
        var t = jquery(e + '>.layui-nav a[href="#' + url + '"]');
        if (t.length === 0) {
            return console.warn(url + " not found")
        }
        var s = jquery(".layui-layout-admin").hasClass("admin-nav-mini");
        if (jquery(e + ">.layui-nav").attr("lay-shrink") === "_all") {
            var i = t.parent("dd").parents(".layui-nav-child");
            if (!s) {
                jquery(e + ">.layui-nav .layui-nav-itemed>.layui-nav-child").not(i).css("display", "block").slideUp("fast", function () {
                    jquery(this).css("display", "")
                })
            }
            jquery(e + ">.layui-nav .layui-nav-itemed").not(i.parent()).removeClass("layui-nav-itemed")
        }
        t.parent().addClass("layui-this");
        var u = t.parent("dd").parents(".layui-nav-child").parent();
        if (!s) {
            var v = u.not(".layui-nav-itemed").children(".layui-nav-child");
            v.slideDown("fast", function () {
                if (jquery(this).is(v.last())) {
                    v.css("display", "");
                    var w = t.offset().top + t.outerHeight() + 30 - admin.getPageHeight();
                    var x = 50 + 65 - t.offset().top;
                    if (w > 0) {
                        jquery(e).animate({"scrollTop": jquery(e).scrollTop() + w}, 300)
                    } else {
                        if (x > 0) {
                            jquery(e).animate({"scrollTop": jquery(e).scrollTop() - x}, 300)
                        }
                    }
                }
            })
        }
        u.addClass("layui-nav-itemed");
        jquery('ul[lay-filter="' + c + '"]').addClass("layui-hide");
        var r = t.parents(".layui-nav");
        r.removeClass("layui-hide");
        jquery(j + ">.layui-nav>.layui-nav-item").removeClass("layui-this");
        jquery(j + '>.layui-nav>.layui-nav-item>a[nav-bind="' + r.attr("nav-id") + '"]').parent().addClass("layui-this")
    };

    /**
     * 打开右侧弹窗
     * @param option
     * @returns {*}
     */
    admin.popupRight = function (option) {

        option.anim = -1;
        option.offset = "r";
        option.move = false;
        option.fixed = true;

        if (option.area === undefined) {
            option.area = "336px"
        }

        if (option.title === undefined) {
            option.title = false
        }

        if (option.closeBtn === undefined) {
            option.closeBtn = false
        }

        if (option.shadeClose === undefined) {
            option.shadeClose = true
        }

        if (option.skin === undefined) {
            option.skin = "layui-anim layui-anim-rl layui-layer-adminRight"
        }

        return admin.open(option)
    };

    /**
     * 打开弹窗
     * @param option 同layer
     * @returns {*}
     */
    admin.open = function (option) {

        if (option.content && option.type === 2) {
            option.url = undefined
        }

        if (option.url && (option.type === 2 || option.type === undefined)) {
            option.type = 1
        }

        if (option.area === undefined) {
            option.area = option.type === 2 ? ["360px", "300px"] : "360px"
        }

        if (option.offset === undefined) {
            option.offset = "70px"
        }

        if (option.shade === undefined) {
            option.shade = 0.1
        }

        if (option.fixed === undefined) {
            option.fixed = false
        }

        if (option.resize === undefined) {
            option.resize = false
        }

        if (option.skin === undefined) {
            option.skin = "layui-layer-admin"
        }

        var endCallback = option.end; // 销毁后回调
        option.end = function () {
            layer.closeAll("tips");
            endCallback && endCallback()
        };
        if (option.url) {
            var successCallback = option.success; // 弹出后回调
            option.success = function (layero, index) {
                jquery(layero).data("tpl", option.tpl || "");
                admin.reloadLayer(index, option.url, successCallback)
            }
        } else {
            if (option.tpl && option.content) {
                option.content = admin.util.tpl(option.content, option.data, setter.tplOpen, setter.tplClose)
            }
        }
        var index = layer.open(option);
        if (option.data) {
            admin.layerData["d" + index] = option.data
        }
        return index
    };

    /**
     * 获取弹窗传递数据
     * @param index
     * @param key
     * @returns {*|null}
     */
    admin.getLayerData = function (index, key) {
        if (index === undefined) {
            index = parent.layer.getFrameIndex(window.name);
            if (index === undefined) {
                return null
            } else {
                return parent.layui.admin.getLayerData(parseInt(index), key)
            }
        } else {
            if (isNaN(index)) {
                index = admin.getLayerIndex(index)
            }
        }
        if (index === undefined) {
            return
        }
        var data = admin.layerData["d" + index];
        if (key && data) {
            return data[key]
        }
        return data
    };

    /**
     * 弹窗传递数据
     * @param key
     * @param value
     * @param index
     * @returns {*}
     */
    admin.putLayerData = function (key, value, index) {
        if (index === undefined) {
            index = parent.layer.getFrameIndex(window.name);
            if (index === undefined) {
                return
            } else {
                return parent.layui.admin.putLayerData(key, value, parseInt(index))
            }
        } else {
            if (isNaN(index)) {
                index = admin.getLayerIndex(index)
            }
        }
        if (index === undefined) {
            return
        }
        var data = admin.getLayerData(index);
        if (!data) {
            data = {}
        }
        data[key] = value;
        admin.layerData["d" + index] = data;
    };

    /**
     * 刷新url方式弹窗
     * @param index
     * @param url
     * @param success
     */
    admin.reloadLayer = function (index, url, success) {
        if (typeof url === "function") {
            success = url;
            url = undefined
        }
        if (isNaN(index)) {
            index = admin.getLayerIndex(index)
        }
        if (index === undefined) {
            return
        }
        var r = jquery("#layui-layer" + index);
        if (url === undefined) {
            url = r.data("url")
        }
        if (!url) {
            return
        }
        r.data("url", url);
        admin.showLoading(r);
        admin.ajax({
            url: url, dataType: "html", success: function (w) {
                admin.removeLoading(r, false);
                if (typeof w !== "string") {
                    w = JSON.stringify(w)
                }
                var u = r.data("tpl");
                if (u === true || u === "true") {
                    var y = admin.getLayerData(index) || {};
                    y.layerIndex = index;
                    var t = jquery("<div>" + w + "</div>"), v = {};
                    t.find("script,[tpl-ignore]").each(function (z) {
                        var A = jquery(this);
                        v["temp_" + z] = A[0].outerHTML;
                        A.after("${temp_" + z + "}").remove()
                    });
                    w = admin.util.tpl(t.html(), y, setter.tplOpen, setter.tplClose);
                    for (var x in v) {
                        w = w.replace("${" + x + "}", v[x])
                    }
                }
                r.children(".layui-layer-content").html(w);
                admin.renderTpl("#layui-layer" + index + " [ew-tpl]");
                success && success(r[0], index)
            }
        })
    };

    /**
     * 封装layer.alert
     * @param content
     * @param options
     * @param yes
     * @returns {*}
     */
    admin.alert = function (content, options, yes) {
        if (typeof options === "function") {
            yes = options;
            options = {}
        }
        if (options.skin === undefined) {
            options.skin = "layui-layer-admin"
        }
        if (options.shade === undefined) {
            options.shade = 0.1
        }
        return layer.alert(content, options, yes)
    };

    /**
     * 封装layer.confirm
     * @param content
     * @param options
     * @param yes
     * @param cancel
     * @returns {*}
     */
    admin.confirm = function (content, options, yes, cancel) {
        if (typeof options === "function") {
            cancel = yes;
            yes = options;
            options = {}
        }
        if (options.skin === undefined) {
            options.skin = "layui-layer-admin"
        }
        if (options.shade === undefined) {
            options.shade = 0.1
        }
        return layer.confirm(content, options, yes, cancel)
    };

    /**
     * 封装layer.prompt
     * @param options
     * @param yes
     * @returns {*}
     */
    admin.prompt = function (options, yes) {
        if (typeof options === "function") {
            yes = options;
            options = {}
        }
        if (options.skin === undefined) {
            options.skin = "layui-layer-admin layui-layer-prompt"
        }
        if (options.shade === undefined) {
            options.shade = 0.1
        }
        return layer.prompt(options, yes)
    };

    /**
     * 封装ajax
     * @param url 请求的url，前面会自动加setter.baseServer
     * @param data 非必填，请求参数
     * @param success 请求回调（网络错误也进此回调，404、403等）
     * @param method 非必填，请求方式，get、post、put、delete等，默认get
     * @param option 非必填，ajax的更多参数，如headers、dataType等
         admin.req('url', {
            username: 'admin',
            password: '123456'
         }, function(res){
            alert(res.code + '-' + res.msg);
         }, 'get', { headers: {} });
     * @returns {*}
     */
    admin.req = function (url, data, success, method, option) {
        if (typeof data === "function") {
            option = method;
            method = success;
            success = data;
            data = {}
        }
        if (method !== undefined && typeof method !== "string") {
            option = method;
            method = undefined
        }
        if (!method) {
            method = "GET"
        }
        if (typeof data === "string") {
            if (!option) {
                option = {}
            }
            if (!option.contentType) {
                option.contentType = "application/json;charset=UTF-8"
            }
        } else {
            if (setter.reqPutToPost) {
                if ("put" === method.toLowerCase()) {
                    method = "POST";
                    data._method = "PUT"
                } else {
                    if ("delete" === method.toLowerCase()) {
                        method = "GET";
                        data._method = "DELETE"
                    }
                }
            }
        }
        // 这里自动加上setter.baseServer
        return admin.ajax(jquery.extend({url: (setter.baseServer || "") + url, data: data, type: method, dataType: "json", success: success}, option))
    };

    /**
     * 封装ajax，同$.ajax
     * @param option
         admin.ajax({
            url: 'url',
            data: {},
            headers: {},
            type: 'post',
            dataType: 'json',
            success: function(res){
                alert(res.code + '-' + res.msg);
            }
        });
     * @returns {*}
     */
    admin.ajax = function (option) {
        var config = admin.util.deepClone(option);
        if (!option.dataType) {
            option.dataType = "json"
        }
        if (!option.headers) {
            option.headers = {}
        }
        var ajaxHeaders = setter.getAjaxHeaders(option.url);
        if (ajaxHeaders) {
            for (var i = 0; i < ajaxHeaders.length; i++) {
                if (option.headers[ajaxHeaders[i].name] === undefined) {
                    option.headers[ajaxHeaders[i].name] = ajaxHeaders[i].value
                }
            }
        }
        var success = option.success;
        option.success = function (data, textStatus, jqXHR) {
            var ajaxSuccessBefore = setter.ajaxSuccessBefore(admin.parseJSON(data), option.url, {
                param: config, reload: function (param) {
                    admin.ajax(jquery.extend(true, config, param)) // true递归对象属性合并
                }, update: function (param) {
                    data = param
                }, xhr: jqXHR
            });
            if (ajaxSuccessBefore !== false) {
                success && success(data, textStatus, jqXHR)
            } else {
                option.cancel && option.cancel()
            }
        };
        option.error = function (jqXHR, textStatus) {
            option.success({code: jqXHR.status, msg: jqXHR.statusText}, textStatus, jqXHR)
        };
        if (layui.cache.version && (!setter.apiNoCache || option.dataType.toLowerCase() !== "json")) {
            if (option.url.indexOf("?") === -1) {
                option.url += "?v="
            } else {
                option.url += "&v="
            }
            if (layui.cache.version === true) { // 不缓存，每次重新获取
                option.url += new Date().getTime()
            } else {
                option.url += layui.cache.version
            }
        }
        return jquery.ajax(option)
    };

    /**
     * 解析json字符串为json对象
     * @param str
     * @returns {any}
     */
    admin.parseJSON = function (str) {
        if (typeof str === "string") {
            try {
                return JSON.parse(str)
            } catch (e) {
            }
        }
        return str
    };

    /**
     * 显示页面加载动画
     * @param elem 非必填 元素选择器，不填为body
     * @param type 非必填 动画类型(1 小球，2 魔方，3信号，4简约)，默认1
     * @param opacity 非必填 透明度(0 - 1)，默认不透明
     * @param size 非必填 尺寸，默认sm，还可以选md大型尺寸
     */
    admin.showLoading = function (elem, type, opacity, size) {
        if (elem !== undefined && (typeof elem !== "string") && !(elem instanceof jquery)) {
            type = elem.type;
            opacity = elem.opacity;
            size = elem.size;
            elem = elem.elem
        }
        if (type === undefined) {
            type = setter.defaultLoading || 1
        }
        if (size === undefined) {
            size = "sm"
        }
        if (elem === undefined) {
            elem = "body"
        }
        var loadHtml = [ // 加载样式
            '<div class="ball-loader ' + size + '"><span></span><span></span><span></span><span></span></div>',
            '<div class="rubik-loader ' + size + '"></div>',
            '<div class="signal-loader ' + size + '"><span></span><span></span><span></span><span></span></div>',
            '<div class="layui-loader ' + size + '"><i class="layui-icon layui-icon-loading layui-anim layui-anim-rotate layui-anim-loop"></i></div>'
        ];
        jquery(elem).addClass("page-no-scroll");
        jquery(elem).scrollTop(0);
        var $loading = jquery(elem).children(".page-loading");
        if ($loading.length <= 0) {
            jquery(elem).append('<div class="page-loading">' + loadHtml[type - 1] + "</div>");
            $loading = jquery(elem).children(".page-loading")
        }
        if (opacity !== undefined) {
            $loading.css("background-color", "rgba(255,255,255," + opacity + ")")
        }
        $loading.show()
    };

    /**
     * 移除加载动画
     * @param elem 非必填 元素选择器，不填为 body
     * @param fade 非必填 true 是淡出效果，false 直接隐藏，默认是 true
     * @param del 非必填 true 是删除，false 是隐藏不删除，默认是 false
     */
    admin.removeLoading = function (elem, fade, del) {
        if (elem === undefined) {
            elem = "body"
        }
        if (fade === undefined) {
            fade = true
        }
        var $pageLoading = jquery(elem).children(".page-loading");
        if (del) {
            $pageLoading.remove()
        } else {
            if (fade) {
                $pageLoading.fadeOut("fast")
            } else {
                $pageLoading.hide()
            }
        }
        jquery(elem).removeClass("page-no-scroll")
    };

    /**
     * 缓存数据
     * @param key
     * @param value
     * @param local true为localStorage存储；false为sessionStorage存储
     */
    admin.putTempData = function (key, value, local) {
        var tableName = local ? setter.tableName : setter.tableName + "_tempData";
        if (value === undefined || value === null) {
            if (local) {
                layui.data(tableName, {key: key, remove: true})
            } else {
                layui.sessionData(tableName, {key: key, remove: true})
            }
        } else {
            if (local) {
                layui.data(tableName, {key: key, value: value})
            } else {
                layui.sessionData(tableName, {key: key, value: value})
            }
        }
    };

    /**
     * 获取缓存数据
     * @param key
     * @param local
     * @returns {*|undefined}
     */
    admin.getTempData = function (key, local) {
        if (typeof key === "boolean") {
            local = key;
            key = undefined
        }
        var i = local ? setter.tableName : setter.tableName + "_tempData";
        var s = local ? layui.data(i) : layui.sessionData(i);
        if (!key) {
            return s
        }
        return s ? s[key] : undefined
    };

    /**
     * 滚动选项卡tab
     * @param direction left、right、auto
     */
    admin.rollPage = function (direction) {
        var q = jquery(layuiTab + ">.layui-tab-title");
        var r = q.scrollLeft();
        if ("left" === direction) {
            q.animate({"scrollLeft": r - 120}, 100)
        } else {
            if ("auto" === direction) {
                var i = 0;
                q.children("li").each(function () {
                    if (jquery(this).hasClass("layui-this")) {
                        return false
                    } else {
                        i += jquery(this).outerWidth()
                    }
                });
                q.animate({"scrollLeft": i - 120}, 100)
            } else {
                q.animate({"scrollLeft": r + 120}, 100)
            }
        }
    };

    /**
     * 刷新指定Tab或当前Tab
     * @param url url，可为空
     */
    admin.refresh = function (url) {
        layRouter.refresh(url)
    };

    /**
     * 关闭url或当前选项卡
     * @param url
     * @returns {*}
     */
    admin.closeThisTabs = function (url) {
        admin.closeTabOperNav();
        var q = jquery(layuiTab + ">.layui-tab-title");
        if (!url) {
            if (q.find("li").first().hasClass("layui-this")) {
                return layer.msg("主页不能关闭", {icon: 2})
            }
            q.find("li.layui-this").find(".layui-tab-close").trigger("click")
        } else {
            if (url === q.find("li").first().attr("lay-id")) {
                return layer.msg("主页不能关闭", {icon: 2})
            }
            q.find('li[lay-id="' + url + '"]').find(".layui-tab-close").trigger("click")
        }
    };

    /**
     * 关闭除url外所有选项卡
     * @param url
     */
    admin.closeOtherTabs = function (url) {
        if (!url) {
            jquery(layuiTab + ">.layui-tab-title li:gt(0):not(.layui-this)").find(".layui-tab-close").trigger("click")
        } else {
            jquery(layuiTab + ">.layui-tab-title li:gt(0)").each(function () {
                if (url !== jquery(this).attr("lay-id")) {
                    jquery(this).find(".layui-tab-close").trigger("click")
                }
            })
        }
        admin.closeTabOperNav()
    };

    /**
     * 关闭所有选项卡
     */
    admin.closeAllTabs = function () {
        jquery(layuiTab + ">.layui-tab-title li:gt(0)").find(".layui-tab-close").trigger("click");
        jquery(layuiTab + ">.layui-tab-title li:eq(0)").trigger("click");
        admin.closeTabOperNav()
    };

    /**
     * 关闭所有菜单项
     */
    admin.closeTabOperNav = function () {
        jquery(".layui-icon-down .layui-nav .layui-nav-child").removeClass("layui-show")
    };

    /**
     * 切换主题
     * @param theme
     * @param win
     * @param noCache
     * @param noChild
     */
    admin.changeTheme = function (theme, win, noCache, noChild) {
        if (!noCache) {
            admin.putSetting("defaultTheme", theme)
        }
        if (!win) {
            win = top
        }
        admin.removeTheme(win);
        if (theme) {
            try {
                var s = win.layui.jquery("body");
                s.addClass(theme);
                s.data("theme", theme)
            } catch (t) {
            }
        }
        if (noChild) {
            return
        }
        var frames = win.frames;
        for (var i = 0; i < frames.length; i++) {
            admin.changeTheme(theme, frames[i], true, false)
        }
    };

    /**
     * 移除主题
     * @param layero
     */
    admin.removeTheme = function (layero) {
        if (!layero) {
            layero = window
        }
        try {
            var body = layero.layui.jquery("body");
            var theme = body.data("theme");
            if (theme) {
                body.removeClass(theme)
            }
            body.removeData("theme")
        } catch (r) {
        }
    };

    /**
     * 关闭当前iframe弹窗
     */
    admin.closeThisDialog = function () {
        return admin.closeDialog()
    };

    /**
     * 关闭elem元素所在的页面层弹窗
     * @param elem dom选择器
     */
    admin.closeDialog = function (elem) {
        if (elem) {
            layer.close(admin.getLayerIndex(elem))
        } else {
            parent.layer.close(parent.layer.getFrameIndex(window.name))
        }
    };

    /**
     * 获取页面层弹窗index
     * @param selector
     * @returns {string|*}
     */
    admin.getLayerIndex = function (selector) {
        if (!selector) {
            return parent.layer.getFrameIndex(window.name)
        }
        var q = jquery(selector).parents(".layui-layer").first().attr("id");
        if (q && q.length >= 11) {
            return q.substring(11)
        }
    };

    /**
     * 让当前的iframe弹层自适应高度
     * @returns {*}
     */
    admin.iframeAuto = function () {
        return parent.layer.iframeAuto(parent.layer.getFrameIndex(window.name))
    };

    /**
     * 获取浏览器高度
     * @returns {number}
     */
    admin.getPageHeight = function () {
        return document.documentElement.clientHeight || document.body.clientHeight
    };

    /**
     * 获取浏览器宽度
     * @returns {number}
     */
    admin.getPageWidth = function () {
        return document.documentElement.clientWidth || document.body.clientWidth
    };

    /**
     * 把弹窗自带按钮跟表单绑定一起
     * @param layero
     * @param btnFilter
     * @param formFilter
     */
    admin.modelForm = function (layero, btnFilter, formFilter) {
        var s = jquery(layero);
        s.addClass("layui-form");
        if (formFilter) {
            s.attr("lay-filter", formFilter)
        }
        var r = s.find(".layui-layer-btn .layui-layer-btn0");
        r.attr("lay-submit", "");
        r.attr("lay-filter", btnFilter)
    };

    /**
     * 设置按钮为加载状态
     * @param elem
     * @param text 修改按钮文字
     * @param loading
     */
    admin.btnLoading = function (elem, text, loading) {
        if (text !== undefined && (typeof text === "boolean")) {
            loading = text;
            text = undefined
        }
        if (text === undefined) {
            text = "&nbsp;加载中"
        }
        if (loading === undefined) {
            loading = true
        }
        var $elem = jquery(elem);
        if (loading) {
            $elem.addClass("ew-btn-loading");
            $elem.prepend('<span class="ew-btn-loading-text"><i class="layui-icon layui-icon-loading layui-anim layui-anim-rotate layui-anim-loop"></i>' + text + "</span>");
            $elem.attr("disabled", "disabled").prop("disabled", true)
        } else {
            $elem.removeClass("ew-btn-loading");
            $elem.children(".ew-btn-loading-text").remove();
            $elem.removeProp("disabled").removeAttr("disabled")
        }
    };

    /**
     * 开启鼠标移入侧边栏自动展开
     */
    admin.openSideAutoExpand = function () {
        var i = jquery(".layui-layout-admin>.layui-side");
        i.off("mouseenter.openSideAutoExpand").on("mouseenter.openSideAutoExpand", function () {
            if (!jquery(this).parent().hasClass("admin-nav-mini")) {
                return
            }
            admin.flexible(true);
            jquery(this).addClass("side-mini-hover")
        });
        i.off("mouseleave.openSideAutoExpand").on("mouseleave.openSideAutoExpand", function () {
            if (!jquery(this).hasClass("side-mini-hover")) {
                return
            }
            admin.flexible(false);
            jquery(this).removeClass("side-mini-hover")
        })
    };

    /**
     * 开启鼠标移入单元格超出自动展开
     */
    admin.openCellAutoExpand = function () {
        var $body = jquery("body");
        $body.off("mouseenter.openCellAutoExpand").on("mouseenter.openCellAutoExpand", ".layui-table-view td", function () {
            jquery(this).find(".layui-table-grid-down").trigger("click")
        });
        $body.off("mouseleave.openCellAutoExpand").on("mouseleave.openCellAutoExpand", ".layui-table-tips>.layui-layer-content", function () {
            jquery(".layui-table-tips-c").trigger("click")
        })
    };

    admin.parseLayerOption = function (option) {
        for (var key in option) {
            if (!option.hasOwnProperty(key)) {
                continue
            }
            if (option[key] && option[key].toString().indexOf(",") !== -1) {
                option[key] = option[key].toString().split(",") // 切分字符串
            }
        }
        var keywords = {"success": "layero,index", "cancel": "index,layero", "end": "", "full": "", "min": "", "restore": ""};
        for (var keywordsKey in keywords) {
            if (!keywords.hasOwnProperty(keywordsKey) || !option[keywordsKey]) {
                continue
            }
            try {
                if (/^[a-zA-Z_]+[a-zA-Z0-9_]+$/.test(option[keywordsKey])) {
                    option[keywordsKey] += "()"
                }
                option[keywordsKey] = new Function(keywords[keywordsKey], option[keywordsKey])
            } catch (e) {
                option[keywordsKey] = undefined
            }
        }
        if (option.content && (typeof option.content === "string") && option.content.indexOf("#") === 0) {
            if (jquery(option.content).is("script")) {
                option.content = jquery(option.content).html()
            } else {
                option.content = jquery(option.content)
            }
        }
        if (option.type === undefined && option.url === undefined) {
            option.type = 2
        }
        return option
    };

    /**
     * 字符的parent.parent转对象
     * @param str
     * @returns {Window}
     */
    admin.strToWin = function (str) {
        var win = window;
        if (!str) {
            return win
        }
        var q = str.split(".");
        for (var i = 0; i < q.length; i++) {
            win = win[q[i]]
        }
        return win
    };

    /**
     * 隐藏表格滚动条
     */
    admin.hideTableScrollBar = function () {
        if (admin.getPageWidth() <= 768) {
            return
        }
        var i = setter.pageTabs ? jquery(layuiTab + ">.layui-tab-content>.layui-tab-item.layui-show") : jquery(layuiBody);
        if (window.hsbTimer) {
            clearTimeout(window.hsbTimer)
        }
        i.find(".layui-table-body.layui-table-main").addClass("no-scrollbar");
        window.hsbTimer = setTimeout(function () {
            i.find(".layui-table-body.layui-table-main").removeClass("no-scrollbar")
        }, 600)
    };

    /**
     * 重置表格大小
     * @param timeout
     */
    admin.resizeTable = function (timeout) {
        setTimeout(function () {
            var q = setter.pageTabs ? jquery(layuiTab + ">.layui-tab-content>.layui-tab-item.layui-show") : jquery(layuiBody);
            q.find(".layui-table-view").each(function () {
                var r = jquery(this).attr("lay-id");
                layui.table && layui.table.resize(r)
            })
        }, timeout === undefined ? 0 : timeout)
    };

    /**
     * 判断当前登录的用户是否具有指定的权限，通过admin.hasPerm(auth)可以控制按钮级别的权限隐藏
     * @param auth
     * @returns {boolean}
     */
    admin.hasPerm = function (auth) {
        var auths = setter.getUserAuths();
        if (auths) {
            for (var i = 0; i < auths.length; i++) {
                if (auth == auths[i]) {
                    return true
                }
            }
        }
        return false
    };

    /**
     * 移除当前登录用户没有权限的dom元素
     * 通过加属性的方式来隐藏：如 <button perm-show="user:add">添加</button>
     * perm-show可以用于任意元素，对于动态添加的元素调用admin.renderPerm()来更新渲染
     */
    admin.renderPerm = function () {
        jquery("[perm-show]").each(function () {
            if (!admin.hasPerm(jquery(this).attr("perm-show"))) {
                jquery(this).remove()
            }
        })
    };

    admin.events = {
        // 折叠侧导航
        flexible: function () {
            admin.strToWin(jquery(this).data("window")).layui.admin.flexible()
        },
        // 刷新主体部分
        refresh: function () {
            admin.strToWin(jquery(this).data("window")).layui.admin.refresh()
        },
        // 浏览器后退
        back: function () {
            admin.strToWin(jquery(this).data("window")).history.back()
        },
        // 打开主题设置弹窗
        theme: function () {
            // <a ew-event="theme" data-url="xxx.html" data-window="parent">主题</a>
            var data = admin.util.deepClone(jquery(this).data()); // 获取dom元素data-属性值
            admin.strToWin(data.window).layui.admin.popupRight(jquery.extend({
                id: "layer-theme",
                url: data.url || "components/tpl/theme.html"
            }, admin.parseLayerOption(data)))
        },
        // 打开便签弹窗
        note: function () {
            // <a ew-event="note" data-url="xxx.html" data-window="parent">打开便签</a>
            var data = admin.util.deepClone(jquery(this).data()); // 获取dom元素data-属性值
            admin.strToWin(data.window).layui.admin.popupRight(jquery.extend({
                id: "layer-note",
                url: data.url || "components/tpl/note.html"
            }, admin.parseLayerOption(data)))
        },
        // 打开消息弹窗
        message: function () {
            // <a ew-event="message" data-url="xxx.html" data-window="parent">弹出消息</a>
            var data = admin.util.deepClone(jquery(this).data()); // 获取dom元素data-属性值
            admin.strToWin(data.window).layui.admin.popupRight(jquery.extend({
                id: "layer-notice",
                url: data.url || "components/tpl/message.html"
            }, admin.parseLayerOption(data)))
        },
        // 打开修改密码弹窗
        psw: function () {
            // <a ew-event="psw" data-url="xxx.html" data-window="parent">修改密码</a>
            var data = admin.util.deepClone(jquery(this).data()); // 获取dom元素data-属性值
            admin.strToWin(data.window).layui.admin.open(jquery.extend({
                id: "layer-psw",
                title: "修改密码",
                shade: 0,
                url: data.url || "components/tpl/password.html"
            }, admin.parseLayerOption(data)))
        },
        // 退出登录
        logout: function () {
            /**
             <a ew-event="logout"
                 data-url="login.html" // 退出登录后跳转的页面地址
                 data-ajax="api/logout" // 退出登录需要请求的ajax接口
                 data-method="post" // ajax请求方式，默认是delete
                 data-code="200" // ajax返回成功的状态码，默认是0
                 data-parse-data="return {code: res.status, msg: res.message}" // 处理接口返回的数据
                 data-confirm="false">退出登录</a> // 是否显示询问框，false表示直接退出不询问，默认true
             */
            var data = admin.util.deepClone(jquery(this).data()); // 获取dom元素data-属性值
            admin.unlockScreen();

            function logoutFun() {
                if (data.ajax) {
                    var loadIndex = layer.load(2);
                    admin.req(data.ajax, function (res) {
                        layer.close(loadIndex);
                        if (data.parseData) {
                            try {
                                var parseData = new Function("res", data.parseData);
                                res = parseData(res)
                            } catch (e) {
                                console.error(e)
                            }
                        }
                        if (res.code == (data.code || 0)) {
                            setter.removeToken && setter.removeToken();
                            location.replace(data.url || "/")
                        } else {
                            layer.msg(res.msg, {icon: 2})
                        }
                    }, data.method || "delete")
                } else {
                    setter.removeToken && setter.removeToken();
                    location.replace(data.url || "/")
                }
            }

            if (false === data.confirm || "false" === data.confirm) {
                return logoutFun()
            }
            admin.strToWin(data.window).layui.layer.confirm(data.content || "确定要退出登录吗？", jquery.extend({
                title: "温馨提示",
                skin: "layui-layer-admin",
                shade: 0.1
            }, admin.parseLayerOption(data)), function () {
                logoutFun()
            })
        },
        // 打开弹窗
        open: function () {
            // <a ew-event="open" data-window="parent">打开</a>
            var data = admin.util.deepClone(jquery(this).data()); // 获取dom元素data-属性值
            admin.strToWin(data.window).layui.admin.open(admin.parseLayerOption(data))
        },
        // 打开右侧弹窗
        popupRight: function () {
            var data = admin.util.deepClone(jquery(this).data()); // 获取dom元素data-属性值
            admin.strToWin(data.window).layui.admin.popupRight(admin.parseLayerOption(data))
        },
        // 全屏切换
        fullScreen: function () {
            var layuiIconScreenFull = "layui-icon-screen-full", layuiIconScreenRestore = "layui-icon-screen-restore";
            var $icon = jquery(this).find("i");
            var fullscreenElement = document.fullscreenElement || document.msFullscreenElement || document.mozFullScreenElement || document.webkitFullscreenElement || false;
            if (fullscreenElement) {
                var exitFullscreen = document.exitFullscreen || document.webkitExitFullscreen || document.mozCancelFullScreen || document.msExitFullscreen;
                if (exitFullscreen) {
                    exitFullscreen.call(document)
                } else {
                    if (window.ActiveXObject) {
                        var activeXObject = new ActiveXObject("WScript.Shell");
                        activeXObject && activeXObject.SendKeys("{F11}")
                    }
                }
                $icon.addClass(layuiIconScreenFull).removeClass(layuiIconScreenRestore)
            } else {
                var documentElement = document.documentElement;
                var requestFullscreen = documentElement.requestFullscreen || documentElement.webkitRequestFullscreen || documentElement.mozRequestFullScreen || documentElement.msRequestFullscreen;
                if (requestFullscreen) {
                    requestFullscreen.call(documentElement)
                } else {
                    if (window.ActiveXObject) {
                        var activeXObject1 = new ActiveXObject("WScript.Shell");
                        activeXObject1 && activeXObject1.SendKeys("{F11}")
                    }
                }
                $icon.addClass(layuiIconScreenRestore).removeClass(layuiIconScreenFull)
            }
        },
        // 左滚动选项卡
        leftPage: function () {
            admin.strToWin(jquery(this).data("window")).layui.admin.rollPage("left")
        },
        // 右滚动选项卡
        rightPage: function () {
            admin.strToWin(jquery(this).data("window")).layui.admin.rollPage()
        },
        // 关闭当前选项卡
        closeThisTabs: function () {
            var i = jquery(this).data("url");
            admin.strToWin(jquery(this).data("window")).layui.admin.closeThisTabs(i)
        },
        // 关闭其他选项卡
        closeOtherTabs: function () {
            admin.strToWin(jquery(this).data("window")).layui.admin.closeOtherTabs()
        },
        // 关闭全部选项卡
        closeAllTabs: function () {
            admin.strToWin(jquery(this).data("window")).layui.admin.closeAllTabs()
        },

        // 关闭弹窗(智能)
        closeDialog: function () {
            if (jquery(this).parents(".layui-layer").length > 0) { // 如果存在父页面，则是弹窗
                admin.closeDialog(this)
            } else { // 否则是iframe类型弹窗
                admin.closeDialog()
            }
        },

        // 关闭iframe类型的弹窗
        closeIframeDialog: function () {
            admin.closeDialog()
        },

        // 关闭当前页面层弹窗
        closePageDialog: function () {
            admin.closeDialog(this)
        },
        // 锁屏
        lockScreen: function () {
            admin.strToWin(jquery(this).data("window")).layui.admin.lockScreen(jquery(this).data("url"))
        }
    };

    /**
     * 地图选择位置
     * @param option
     */
    admin.chooseLocation = function (option) {

        var title = option.title; // 弹窗标题
        var onSelect = option.onSelect; // 选择回调
        var needCity = option.needCity; // 是否返回行政区，省市区默认不返回
        var center = option.center; // 地图默认的中心点
        var defaultZoom = option.defaultZoom; // 地图默认缩放级别
        var pointZoom = option.pointZoom; // 选中时地图的缩放级别
        var keywords = option.keywords; // poi检索关键字，例如：建筑、写字楼
        var pageSize = option.pageSize; // poi检索最大数量
        var mapJsUrl = option.mapJsUrl; // 高德地图js的url

        if (title === undefined) {
            title = "选择位置"
        }
        if (defaultZoom === undefined) {
            defaultZoom = 11
        }
        if (pointZoom === undefined) {
            pointZoom = 17
        }
        if (keywords === undefined) {
            keywords = ""
        }
        if (pageSize === undefined) {
            pageSize = 30
        }
        if (mapJsUrl === undefined) { // 高德地图js的url
            mapJsUrl = "https://webapi.amap.com/maps?v=1.4.14&key=006d995d433058322319fa797f2876f5"
        }

        var D = false, A;
        var w = function (F, E) {
            AMap.service(["AMap.PlaceSearch"], function () {
                var H = new AMap.PlaceSearch({type: "", pageSize: pageSize, pageIndex: 1});
                var G = [E, F];
                H.searchNearBy(keywords, G, 1000, function (J, I) {
                    if (J === "complete") {
                        var M = I.poiList.pois;
                        var html = "";
                        for (var L = 0; L < M.length; L++) {
                            var K = M[L];
                            if (K.location !== undefined) {
                                html += '<div data-lng="' + K.location.lng + '" data-lat="' + K.location.lat + '" class="ew-map-select-search-list-item">';
                                html += '     <div class="ew-map-select-search-list-item-title">' + K.name + "</div>";
                                html += '     <div class="ew-map-select-search-list-item-address">' + K.address + "</div>";
                                html += '     <div class="ew-map-select-search-list-item-icon-ok layui-hide"><i class="layui-icon layui-icon-ok-circle"></i></div>';
                                html += "</div>"
                            }
                        }
                        jquery("#ew-map-select-pois").html(html)
                    }
                })
            })
        };

        var i = function () {
            var E = {resizeEnable: true, zoom: defaultZoom};
            center && (E.center = center);
            var G = new AMap.Map("ew-map-select-map", E);
            G.on("complete", function () {
                var H = G.getCenter();
                w(H.lat, H.lng)
            });
            G.on("moveend", function () {
                if (D) {
                    D = false
                } else {
                    jquery("#ew-map-select-tips").addClass("layui-hide");
                    jquery("#ew-map-select-center-img").removeClass("bounceInDown");
                    setTimeout(function () {
                        jquery("#ew-map-select-center-img").addClass("bounceInDown")
                    });
                    var H = G.getCenter();
                    w(H.lat, H.lng)
                }
            });
            jquery("#ew-map-select-pois").off("click").on("click", ".ew-map-select-search-list-item", function () {
                jquery("#ew-map-select-tips").addClass("layui-hide");
                jquery("#ew-map-select-pois .ew-map-select-search-list-item-icon-ok").addClass("layui-hide");
                jquery(this).find(".ew-map-select-search-list-item-icon-ok").removeClass("layui-hide");
                jquery("#ew-map-select-center-img").removeClass("bounceInDown");
                setTimeout(function () {
                    jquery("#ew-map-select-center-img").addClass("bounceInDown")
                });
                var lng = jquery(this).data("lng");
                var lat = jquery(this).data("lat");
                var name = jquery(this).find(".ew-map-select-search-list-item-title").text();
                var address = jquery(this).find(".ew-map-select-search-list-item-address").text();
                A = {name: name, address: address, lat: lat, lng: lng};
                D = true;
                G.setZoomAndCenter(pointZoom, [lng, lat])
            });
            jquery("#ew-map-select-btn-ok").click(function () {
                if (A === undefined) {
                    layer.msg("请点击位置列表选择", {icon: 2, anim: 6})
                } else {
                    if (onSelect) {
                        if (needCity) {
                            var H = layer.load(2);
                            G.setCenter([A.lng, A.lat]);
                            G.getCity(function (I) {
                                layer.close(H);
                                A.city = I;
                                admin.closeDialog("#ew-map-select-btn-ok");
                                onSelect(A)
                            })
                        } else {
                            admin.closeDialog("#ew-map-select-btn-ok");
                            onSelect(A)
                        }
                    } else {
                        admin.closeDialog("#ew-map-select-btn-ok")
                    }
                }
            });
            var F = jquery("#ew-map-select-input-search");
            F.off("input").on("input", function () {
                var H = jquery(this).val();
                var I = jquery("#ew-map-select-tips");
                if (!H) {
                    I.html("");
                    I.addClass("layui-hide")
                }
                AMap.plugin("AMap.Autocomplete", function () {
                    var J = new AMap.Autocomplete({city: "全国"});
                    J.search(H, function (M, L) {
                        if (L.tips) {
                            var K = L.tips;
                            var O = "";
                            for (var N = 0; N < K.length; N++) {
                                var P = K[N];
                                if (P.location !== undefined) {
                                    O += '<div data-lng="' + P.location.lng + '" data-lat="' + P.location.lat + '" class="ew-map-select-search-list-item">';
                                    O += '     <div class="ew-map-select-search-list-item-icon-search"><i class="layui-icon layui-icon-search"></i></div>';
                                    O += '     <div class="ew-map-select-search-list-item-title">' + P.name + "</div>";
                                    O += '     <div class="ew-map-select-search-list-item-address">' + P.address + "</div>";
                                    O += "</div>"
                                }
                            }
                            I.html(O);
                            if (K.length === 0) {
                                jquery("#ew-map-select-tips").addClass("layui-hide")
                            } else {
                                jquery("#ew-map-select-tips").removeClass("layui-hide")
                            }
                        } else {
                            I.html("");
                            I.addClass("layui-hide")
                        }
                    })
                })
            });
            F.off("blur").on("blur", function () {
                var H = jquery(this).val();
                var I = jquery("#ew-map-select-tips");
                if (!H) {
                    I.html("");
                    I.addClass("layui-hide")
                }
            });
            F.off("focus").on("focus", function () {
                var H = jquery(this).val();
                if (H) {
                    jquery("#ew-map-select-tips").removeClass("layui-hide")
                }
            });
            jquery("#ew-map-select-tips").off("click").on("click", ".ew-map-select-search-list-item", function () {
                jquery("#ew-map-select-tips").addClass("layui-hide");
                var H = jquery(this).data("lng");
                var I = jquery(this).data("lat");
                A = undefined;
                G.setZoomAndCenter(pointZoom, [H, I])
            })
        };

        var content = [
            '<div class="ew-map-select-tool" style="position: relative;">',
            '     搜索：<input id="ew-map-select-input-search" class="layui-input icon-search inline-block" style="width: 190px;" placeholder="输入关键字搜索" autocomplete="off" />',
            '     <button id="ew-map-select-btn-ok" class="layui-btn icon-btn pull-right" type="button"><i class="layui-icon">&#xe605;</i>确定</button>',
            '     <div id="ew-map-select-tips" class="ew-map-select-search-list layui-hide">',
            "     </div>",
            "</div>",
            '<div class="layui-row ew-map-select">',
            '     <div class="layui-col-sm7 ew-map-select-map-group" style="position: relative;">',
            '          <div id="ew-map-select-map"></div>',
            '          <i id="ew-map-select-center-img2" class="layui-icon layui-icon-add-1"></i>',
            '          <img id="ew-map-select-center-img" src="https://3gimg.qq.com/lightmap/components/locationPicker2/image/marker.png" alt=""/>',
            "     </div>",
            '     <div id="ew-map-select-pois" class="layui-col-sm5 ew-map-select-search-list">',
            "     </div>",
            "</div>"
        ].join("");

        admin.open({
            id: "ew-map-select", type: 1, title: title, area: "750px", content: content, success: function (selector, G) {
                var F = jquery(selector).children(".layui-layer-content");
                F.css("overflow", "visible");
                admin.showLoading(F);
                if (undefined === window.AMap) {
                    jquery.getScript(mapJsUrl, function () {
                        i();
                        admin.removeLoading(F)
                    })
                } else {
                    i();
                    admin.removeLoading(F)
                }
            }
        })
    };

    /**
     * 裁剪图片
     * @param option
     */
    admin.cropImg = function (option) {
        var defaultImgType = "image/jpeg";
        var aspectRatio = option.aspectRatio; // 裁剪比例，例如：16/9
        var imgSrc = option.imgSrc; // 要裁剪的图片，无则先弹出选择图片
        var imgType = option.imgType; // 裁剪的图片类型，非必填
        var onCrop = option.onCrop; // 裁剪完成回调
        var limitSize = option.limitSize; // 限制选择的图片大小
        var acceptMime = option.acceptMime; // 限制选择的图片类型
        var exts = option.exts; // 限制选择的图片后缀
        var title = option.title; // 弹窗标题

        if (aspectRatio === undefined) {
            aspectRatio = 1
        }
        if (title === undefined) {
            title = "裁剪图片"
        }
        if (imgType) {
            defaultImgType = imgType
        }
        layui.use(["Cropper", "upload"], function () {
            var A = layui.Cropper, z = layui.upload;

            function B() {
                var E, F = jquery("#ew-crop-img");
                var G = {
                    elem: "#ew-crop-img-upload", auto: false, drag: false, choose: function (H) {
                        H.preview(function (J, K, I) {
                            defaultImgType = K.type;
                            F.attr("src", I);
                            if (!imgSrc || !E) {
                                imgSrc = I;
                                B()
                            } else {
                                E.destroy();
                                E = new A(F[0], D)
                            }
                        })
                    }
                };
                if (limitSize !== undefined) {
                    G.size = limitSize
                }
                if (acceptMime !== undefined) {
                    G.acceptMime = acceptMime
                }
                if (exts !== undefined) {
                    G.exts = exts
                }
                z.render(G);
                if (!imgSrc) {
                    return jquery("#ew-crop-img-upload").trigger("click")
                }
                var D = {aspectRatio: aspectRatio, preview: "#ew-crop-img-preview"};
                E = new A(F[0], D);
                jquery(".ew-crop-tool").on("click", "[data-method]", function () {
                    var I = jquery(this).data(), J, H;
                    if (!E || !I.method) {
                        return
                    }
                    I = jquery.extend({}, I);
                    J = E.cropped;
                    switch (I.method) {
                        case"rotate":
                            if (J && D.viewMode > 0) {
                                E.clear()
                            }
                            break;
                        case"getCroppedCanvas":
                            if (defaultImgType === "image/jpeg") {
                                if (!I.option) {
                                    I.option = {}
                                }
                                I.option.fillColor = "#fff"
                            }
                            break
                    }
                    H = E[I.method](I.option, I.secondOption);
                    switch (I.method) {
                        case"rotate":
                            if (J && D.viewMode > 0) {
                                E.crop()
                            }
                            break;
                        case"scaleX":
                        case"scaleY":
                            jquery(this).data("option", -I.option);
                            break;
                        case"getCroppedCanvas":
                            if (H) {
                                onCrop && onCrop(H.toDataURL(defaultImgType));
                                admin.closeDialog("#ew-crop-img")
                            } else {
                                layer.msg("裁剪失败", {icon: 2, anim: 6})
                            }
                            break
                    }
                })
            }

            var content = [
                '<div class="layui-row">',
                '     <div class="layui-col-sm8" style="min-height: 9rem;">',
                '          <img id="ew-crop-img" src="', imgSrc || "",
                '" style="max-width:100%;" alt=""/>',
                "     </div>",
                '     <div class="layui-col-sm4 layui-hide-xs" style="padding: 15px;text-align: center;">',
                '          <div id="ew-crop-img-preview" style="width: 100%;height: 9rem;overflow: hidden;display: inline-block;border: 1px solid #dddddd;"></div>',
                "     </div>",
                "</div>",
                '<div class="text-center ew-crop-tool" style="padding: 15px 10px 5px 0;">',
                '     <div class="layui-btn-group" style="margin-bottom: 10px;margin-left: 10px;">',
                '          <button title="放大" data-method="zoom" data-option="0.1" class="layui-btn icon-btn" type="button"><i class="layui-icon layui-icon-add-1"></i></button>',
                '          <button title="缩小" data-method="zoom" data-option="-0.1" class="layui-btn icon-btn" type="button"><span style="display: inline-block;width: 12px;height: 2.5px;background: rgba(255, 255, 255, 0.9);vertical-align: middle;margin: 0 4px;"></span></button>',
                "     </div>",
                '     <div class="layui-btn-group layui-hide-xs" style="margin-bottom: 10px;">',
                '          <button title="向左旋转" data-method="rotate" data-option="-45" class="layui-btn icon-btn" type="button"><i class="layui-icon layui-icon-refresh-1" style="transform: rotateY(180deg) rotate(40deg);display: inline-block;"></i></button>',
                '          <button title="向右旋转" data-method="rotate" data-option="45" class="layui-btn icon-btn" type="button"><i class="layui-icon layui-icon-refresh-1" style="transform: rotate(30deg);display: inline-block;"></i></button>',
                "     </div>",
                '     <div class="layui-btn-group" style="margin-bottom: 10px;">',
                '          <button title="左移" data-method="move" data-option="-10" data-second-option="0" class="layui-btn icon-btn" type="button"><i class="layui-icon layui-icon-left"></i></button>',
                '          <button title="右移" data-method="move" data-option="10" data-second-option="0" class="layui-btn icon-btn" type="button"><i class="layui-icon layui-icon-right"></i></button>',
                '          <button title="上移" data-method="move" data-option="0" data-second-option="-10" class="layui-btn icon-btn" type="button"><i class="layui-icon layui-icon-up"></i></button>',
                '          <button title="下移" data-method="move" data-option="0" data-second-option="10" class="layui-btn icon-btn" type="button"><i class="layui-icon layui-icon-down"></i></button>',
                "     </div>",
                '     <div class="layui-btn-group" style="margin-bottom: 10px;">',
                '          <button title="左右翻转" data-method="scaleX" data-option="-1" class="layui-btn icon-btn" type="button" style="position: relative;width: 41px;"><i class="layui-icon layui-icon-triangle-r" style="position: absolute;left: 9px;top: 0;transform: rotateY(180deg);font-size: 16px;"></i><i class="layui-icon layui-icon-triangle-r" style="position: absolute; right: 3px; top: 0;font-size: 16px;"></i></button>',
                '          <button title="上下翻转" data-method="scaleY" data-option="-1" class="layui-btn icon-btn" type="button" style="position: relative;width: 41px;"><i class="layui-icon layui-icon-triangle-d" style="position: absolute;left: 11px;top: 6px;transform: rotateX(180deg);line-height: normal;font-size: 16px;"></i><i class="layui-icon layui-icon-triangle-d" style="position: absolute; left: 11px; top: 14px;line-height: normal;font-size: 16px;"></i></button>',
                "     </div>",
                '     <div class="layui-btn-group" style="margin-bottom: 10px;">',
                '          <button title="重新开始" data-method="reset" class="layui-btn icon-btn" type="button"><i class="layui-icon layui-icon-refresh"></i></button>',
                '          <button title="选择图片" id="ew-crop-img-upload" class="layui-btn icon-btn" type="button" style="border-radius: 0 2px 2px 0;"><i class="layui-icon layui-icon-upload-drag"></i></button>',
                "     </div>",
                '     <button data-method="getCroppedCanvas" data-option="{ &quot;maxWidth&quot;: 4096, &quot;maxHeight&quot;: 4096 }" class="layui-btn icon-btn" type="button" style="margin-left: 10px;margin-bottom: 10px;"><i class="layui-icon">&#xe605;</i>完成</button>',
                "</div>"
            ].join("");

            admin.open({
                title: title, area: "665px", type: 1, content: content, success: function (selector, E) {
                    jquery(selector).children(".layui-layer-content").css("overflow", "visible");
                    B()
                }
            })
        })
    };

    admin.util = {
        // 百度地图坐标转高德地图坐标
        Convert_BD09_To_GCJ02: function (point) {
            var s = (3.141592653589793 * 3000) / 180;
            var i = point.lng - 0.0065, u = point.lat - 0.006;
            var t = Math.sqrt(i * i + u * u) - 0.00002 * Math.sin(u * s);
            var r = Math.atan2(u, i) - 0.000003 * Math.cos(i * s);
            return {lng: t * Math.cos(r), lat: t * Math.sin(r)}
        },
        // 高德地图坐标转百度地图坐标
        Convert_GCJ02_To_BD09: function (point) {
            var s = (3.141592653589793 * 3000) / 180;
            var i = point.lng, u = point.lat;
            var t = Math.sqrt(i * i + u * u) + 0.00002 * Math.sin(u * s);
            var r = Math.atan2(u, i) + 0.000003 * Math.cos(i * s);
            return {lng: t * Math.cos(r) + 0.0065, lat: t * Math.sin(r) + 0.006}
        },
        /**
         * 动态数字
         * @param elem 需要动画的元素
         * @param isThd 是否开启千分位，开启后每进千加逗号分隔
         * @param delay 动画间隔，默认500
         * @param grain 动画粒度，默认100
         */
        animateNum: function (elem, isThd, delay, grain) {
            isThd = isThd === null || isThd === undefined || isThd === true || isThd === "true";
            delay = isNaN(delay) ? 500 : delay;
            grain = isNaN(grain) ? 100 : grain;
            var t = function (y) {
                var w = "";
                for (var x = 0; x < y.length; x++) {
                    if (!isNaN(y.charAt(x))) {
                        return w
                    } else {
                        w += y.charAt(x)
                    }
                }
            }, i = function (y) {
                var w = "";
                for (var x = y.length - 1; x >= 0; x--) {
                    if (!isNaN(y.charAt(x))) {
                        return w
                    } else {
                        w = y.charAt(x) + w
                    }
                }
            }, r = function (x, w) {
                if (!w) {
                    return x
                }
                if (!/^[0-9]+.?[0-9]*$/.test(x)) {
                    return x
                }
                x = x.toString();
                return x.replace(x.indexOf(".") > 0 ? /(\d)(?=(\d{3})+(?:\.))/g : /(\d)(?=(\d{3})+(?:$))/g, "$1,")
            };
            jquery(elem).each(function () {
                var C = jquery(this);
                var z = C.data("num");
                if (!z) {
                    z = C.text().replace(/,/g, "");
                    C.data("num", z)
                }
                var B = "INPUT,TEXTAREA".indexOf(C.get(0).tagName) >= 0;
                var I = t(z.toString()), F = i(z.toString());
                var H = z.toString().replace(I, "").replace(F, "");
                if (isNaN(H * 1) || H === "0") {
                    B ? C.val(z) : C.html(z);
                    return console.error("not a number")
                }
                var w = H.split(".");
                var D = w[1] ? w[1].length : 0;
                var y = 0, E = H;
                if (Math.abs(E * 1) > 10) {
                    y = parseFloat(w[0].substring(0, w[0].length - 1) + (w[1] ? ".0" + w[1] : ""))
                }
                var A = (E - y) / grain, G = 0;
                var x = setInterval(function () {
                    var J = I + r(y.toFixed(D), isThd) + F;
                    B ? C.val(J) : C.html(J);
                    y += A;
                    G++;
                    if (Math.abs(y) >= Math.abs(E * 1) || G > 5000) {
                        J = I + r(E, isThd) + F;
                        B ? C.val(J) : C.html(J);
                        clearInterval(x)
                    }
                }, delay / grain)
            })
        },
        // 深度克隆对象，对象型在参数传递时通常是引用传递，有时需要把对象克隆一份再传递，避免传递的参数被修改导致第二次传递出现问题。
        deepClone: function (obj) {
            var cloneObj;
            var classType = admin.util.isClass(obj);
            if (classType === "Object") {
                cloneObj = {}
            } else {
                if (classType === "Array") {
                    cloneObj = []
                } else {
                    return obj
                }
            }
            for (var property in obj) {
                if (!obj.hasOwnProperty(property)) {
                    continue
                }
                var val = obj[property], type = admin.util.isClass(val);
                if (type === "Object") {
                    cloneObj[property] = arguments.callee(val)
                } else {
                    if (type === "Array") {
                        cloneObj[property] = arguments.callee(val)
                    } else {
                        cloneObj[property] = obj[property]
                    }
                }
            }
            return cloneObj
        },

        isClass: function (obj) {
            if (obj === null) {
                return "Null"
            }
            if (obj === undefined) {
                return "Undefined"
            }
            return Object.prototype.toString.call(obj).slice(8, -1)
        },

        // 判断富文本是否为空，判断规则，有文字，有img、audio、video、iframe等标签都属于不为空。
        fullTextIsEmpty: function (text) {
            if (!text) {
                return true
            }
            var r = ["img", "audio", "video", "iframe", "object"];
            for (var q = 0; q < r.length; q++) {
                if (text.indexOf("<" + r[q]) > -1) {
                    return false
                }
            }
            var s = text.replace(/\s*/g, "");
            if (!s) {
                return true
            }
            s = s.replace(/&nbsp;/ig, "");
            if (!s) {
                return true
            }
            s = s.replace(/<[^>]+>/g, "");
            return !s
        },
        // 移除元素的style，有多个内联样式style，如何只移除其中一个或多个呢
        removeStyle: function (elem, options) {
            if (typeof options === "string") {
                options = [options]
            }
            for (var q = 0; q < options.length; q++) {
                jquery(elem).css(options[q], "")
            }
        },
        // 滚动到顶部
        scrollTop: function (elem) {
            if (!elem) { // 让html、body滚动到顶部
                var q = jquery(".layui-layout-admin>.layui-body");
                elem = q.children(".layui-tab").children(".layui-tab-content").children(".layui-tab-item.layui-show");
                if (elem.length === 0) {
                    elem = q.children(".layui-body-header.show+div");
                    if (elem.length === 0) {
                        elem = q
                    }
                }
            } else { // 自定义元素滚动到顶部
                elem = jquery(elem)
            }
            elem.animate({scrollTop: 0}, 300)
        },
        // 模板解析，它与laytpl使用方式一致，并且解决了laytpl对js注释支持不友好，laytpl模板中有js注释会导致最后渲染的内容有问题
        tpl: function (html, data, openCode, closeCode) {
            if (html === undefined || html === null || typeof html !== "string") {
                return html
            }

            if (!data) {
                data = {}
            }

            if (!openCode) {
                openCode = "{{"
            }

            if (!closeCode) {
                closeCode = "}}"
            }

            var templateParsingEngine = {
                exp: function (expression) {
                    return new RegExp(expression, "g")
                },

                query: function (w, u, x) {
                    var v = ["#([\\s\\S])+?", "([^{#}])*?"][w || 0];
                    return templateParsingEngine.exp((u || "") + openCode + v + closeCode + (x || ""))
                },

                escape: function (str) {
                    return String(str || "").replace(/&(?!#?[a-zA-Z0-9]+;)/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/'/g, "&#39;").replace(/"/g, "&quot;")
                },

                error: function (e, template) {
                    console.error("Laytpl Error：" + e + "\n" + (template || ""))
                },

                parse: function (html, data) {
                    var template = html;

                    try {
                        var y = templateParsingEngine.exp("^" + openCode + "#"),
                            z = templateParsingEngine.exp(closeCode + "$");

                        html = html.replace(templateParsingEngine.exp(openCode + "#"), openCode + "# ")
                            .replace(templateParsingEngine.exp(closeCode + "}"), "} " + closeCode)
                            .replace(/\\/g, "\\\\")
                            .replace(templateParsingEngine.exp(openCode + "!(.+?)!" + closeCode), function (match) {
                            match = match.replace(templateParsingEngine.exp("^" + openCode + "!"), "").replace(templateParsingEngine.exp("!" + closeCode), "").replace(templateParsingEngine.exp(openCode + "|" + closeCode), function (match) {
                                return match.replace(/(.)/g, "\\$1")
                            });
                            return match
                        }).replace(/(?="|')/g, "\\")
                            .replace(templateParsingEngine.query(), function (match) {
                            match = match.replace(y, "").replace(z, "");
                            return '";' + match.replace(/\\/g, "") + ';view+="'
                        }).replace(templateParsingEngine.query(1), function (match) {
                            var B = '"+(';
                            if (match.replace(/\s/g, "") === openCode + closeCode) {
                                return ""
                            }
                            match = match.replace(templateParsingEngine.exp(openCode + "|" + closeCode), "");
                            if (/^=/.test(match)) {
                                match = match.replace(/^=/, "");
                                B = '"+_escape_('
                            }
                            return B + match.replace(/\\/g, "") + ')+"'
                        }).replace(/\r\n/g, '\\r\\n" + "')
                            .replace(/\n/g, '\\n" + "')
                            .replace(/\r/g, '\\r" + "');

                        // {{变量}}被替换为(变量)，到这里变量没有替换为对应的值
                        html = '"use strict";var view = "' + html + '";return view;';
                        // d为用户传入变量，_escape_为转义函数
                        html = new Function("d, _escape_", html);
                        // 执行函数并替换对应变量
                        return html(data, templateParsingEngine.escape)
                    } catch (e) {
                        templateParsingEngine.error(e, template);
                        return template
                    }
                }
            };

            return templateParsingEngine.parse(html, data)
        },

        render: function (data) {
            if (typeof data.url === "string") {
                data.success = function (url) {
                    admin.util.render(jquery.extend({}, data, {url: url}))
                };
                if (data.ajax === "ajax") {
                    admin.ajax(data)
                } else {
                    admin.req(data.url, data.where, data.success, data.method, data)
                }
                return
            }
            var tplHtml = admin.util.tpl(data.tpl, data.url, data.open || setter.tplOpen, data.close || setter.tplClose);
            jquery(data.elem).next("[ew-tpl-rs]").remove();
            jquery(data.elem).after(tplHtml);
            jquery(data.elem).next().attr("ew-tpl-rs", "");
            data.done && data.done(data.url)
        }
    };

    /**
     * 锁屏
     * @param url url是锁屏页面地址，不填为默认地址
     */
    admin.lockScreen = function (url) {
        if (!url) {
            url = "components/tpl/lock-screen.html"
        }
        var i = jquery("#ew-lock-screen-group");
        if (i.length > 0) {
            i.fadeIn("fast");
            admin.isLockScreen = true;
            admin.putTempData("isLockScreen", admin.isLockScreen, true)
        } else {
            var q = layer.load(2);
            admin.ajax({
                url: url, dataType: "html", success: function (s) {
                    layer.close(q);
                    if (typeof s === "string") {
                        jquery("body").append('<div id="ew-lock-screen-group">' + s + "</div>");
                        admin.isLockScreen = true;
                        admin.putTempData("isLockScreen", admin.isLockScreen, true);
                        admin.putTempData("lockScreenUrl", url, true)
                    } else {
                        console.error(s);
                        layer.msg(JSON.stringify(s), {icon: 2, anim: 6})
                    }
                }
            })
        }
    };

    /**
     * 解除锁屏
     * @param isRemove 移除锁屏页面，下次锁屏需要重新加载页面
     */
    admin.unlockScreen = function (isRemove) {
        var $lockScreenGroup = jquery("#ew-lock-screen-group");
        isRemove ? $lockScreenGroup.remove() : $lockScreenGroup.fadeOut("fast");
        admin.isLockScreen = false;
        admin.putTempData("isLockScreen", null, true)
    };

    /**
     * 增强layer.tips
     * @param options
         options = {
            direction： 设置位置，1上面(默认)、2右边、3下面、4左边
            bg： 设置背景颜色(包含箭头颜色,下面的背景图片不包含箭头)
            offset： 设置偏移距离，(上，左)
            padding：内间距
            color：文字颜色
            bgImg：背景图片，例如lay-bgImg="url(assets/images/head.jpg)"
            fontSize：字体大小
         }
     * @returns {*}
     */
    admin.tips = function (options) {
        return layer.tips(options.text, options.elem, {
            tips: [options.direction || 1, options.bg || "#191a23"],
            tipsMore: options.tipsMore,
            time: options.time || -1,
            success: function (layero) {
                var $layuiLayerContent = jquery(layero).children(".layui-layer-content");
                if (options.padding || options.padding === 0) {
                    $layuiLayerContent.css("padding", options.padding)
                }
                if (options.color) {
                    $layuiLayerContent.css("color", options.color)
                }
                if (options.bgImg) {
                    $layuiLayerContent.css("background-image", options.bgImg).children(".layui-layer-TipsG").css("z-index", "-1")
                }
                if (options.fontSize) {
                    $layuiLayerContent.css("font-size", options.fontSize)
                }
                if (!options.offset) {
                    return
                }
                var area = options.offset.split(",");
                var height = area[0], width = area.length > 1 ? area[1] : undefined;
                if (height) {
                    jquery(layero).css("margin-top", height)
                }
                if (width) {
                    jquery(layero).css("margin-left", width)
                }
            }
        })
    };

    /**
     * 动态模板渲染
     * @param selector jquery选择器
     */
    admin.renderTpl = function (selector) {
        if (!layui.admin) {
            layui.admin = admin
        }

        // 替换模板中变量
        function tplVariableReplace(tpl) {
            if (!tpl) {
                return
            }
            try {
                return new Function("return " + tpl + ";")()
            } catch (s) {
                console.error(s + "\nlay-data: " + tpl)
            }
        }

        // 通过ew-tpl来表示这是一个动态模板以及设置数据源
        jquery(selector || "[ew-tpl]").each(function () {
            var template = jquery(this);
            var data = admin.util.deepClone(jquery(this).data()); // 获取模板所有data-属性
            data.elem = template;
            data.tpl = template.html();
            data.url = tplVariableReplace(template.attr("ew-tpl")); // 远程数据的url
            data.headers = tplVariableReplace(data.headers); // 远程数据的请求header
            data.where = tplVariableReplace(data.where); // 远程数据的请求条件,也可以data-where="JSON.stringify({})"

            if (data.done) { // 渲染完成后的回调
                try {
                    data.done = new Function("res", data.done)
                } catch (s) {
                    console.error(s + "\nlay-data:" + data.done);
                    data.done = undefined
                }
            }

            admin.util.render(data)
        })
    };

    /**
     * admin模块事件监听
     * @param event 事件名称
     * @param callback 回调函数，如果为空，则执行事件监听器，否则为注册事件监听器
     * @returns {*}
     */
    admin.on = function (event, callback) {
        return layui.onevent.call(this, "admin", event, callback)
    };

    /**
     * 修改配置信息
     * @param key
     * @param value
     */
    admin.putSetting = function (key, value) {
        setter[key] = value;
        admin.putTempData(key, value, true)
    };

    /**
     * 恢复配置信息
     */
    admin.recoverState = function () {
        if (admin.getTempData("isLockScreen", true)) { // 锁屏
            admin.lockScreen(admin.getTempData("lockScreenUrl", true))
        }
        if (setter.defaultTheme) { // 默认主题
            admin.changeTheme(setter.defaultTheme, window, true, true)
        }
        if (setter.closeFooter) {
            jquery("body").addClass("close-footer")
        }
        if (setter.navArrow !== undefined) {
            var i = jquery(e + ">.layui-nav-tree");
            i.removeClass("arrow2 arrow3");
            if (setter.navArrow) {
                i.addClass(setter.navArrow)
            }
        }
        if (setter.pageTabs && setter.tabAutoRefresh == "true") {
            jquery(layuiTab).attr("lay-autoRefresh", "true")
        }
    };

    var m = ".layui-layout-admin.admin-nav-mini>.layui-side .layui-nav .layui-nav-item";
    jquery(document).on("mouseenter", m + "," + m + " .layui-nav-child>dd", function () {
        if (admin.getPageWidth() > 768) {
            var i = jquery(this), r = i.find(">.layui-nav-child");
            if (r.length > 0) {
                i.addClass("admin-nav-hover");
                r.css("left", i.offset().left + i.outerWidth());
                var q = i.offset().top;
                if (q + r.outerHeight() > admin.getPageHeight()) {
                    q = q - r.outerHeight() + i.outerHeight();
                    if (q < 60) {
                        q = 60
                    }
                    r.addClass("show-top")
                }
                r.css("top", q);
                r.addClass("ew-anim-drop-in")
            } else {
                if (i.hasClass("layui-nav-item")) {
                    admin.tips({elem: i, text: i.find("cite").text(), direction: 2, offset: "12px"})
                }
            }
        }
    }).on("mouseleave", m + "," + m + " .layui-nav-child>dd", function () {
        layer.closeAll("tips");
        var q = jquery(this);
        q.removeClass("admin-nav-hover");
        var i = q.find(">.layui-nav-child");
        i.removeClass("show-top ew-anim-drop-in");
        i.css({"left": "auto", "top": "auto"})
    });

    /**
     <a ew-event="fullScreen">全屏</a>
     <a ew-event="flexible">折叠导航</a>
     */
    jquery(document).on("click", "*[ew-event]", function () {
        var event = admin.events[jquery(this).attr("ew-event")];
        event && event.call(this, jquery(this))
    });

    jquery(document).on("mouseenter", "*[lay-tips]", function () {
        var i = jquery(this);
        admin.tips({
            elem: i,
            text: i.attr("lay-tips"),
            direction: i.attr("lay-direction"),
            bg: i.attr("lay-bg"),
            offset: i.attr("lay-offset"),
            padding: i.attr("lay-padding"),
            color: i.attr("lay-color"),
            bgImg: i.attr("lay-bgImg"),
            fontSize: i.attr("lay-fontSize")
        })
    }).on("mouseleave", "*[lay-tips]", function () {
        layer.closeAll("tips")
    });

    jquery(document).on("click", ".form-search-expand,[search-expand]", function () {
        var s = jquery(this);
        var q = s.parents(".layui-form").first();
        var r = s.data("expand");
        var t = s.attr("search-expand");
        if (r === undefined || r === true) {
            r = true;
            s.data("expand", false);
            s.html('收起 <i class="layui-icon layui-icon-up"></i>');
            var i = q.find(".form-search-show-expand");
            i.attr("expand-show", "");
            i.removeClass("form-search-show-expand")
        } else {
            r = false;
            s.data("expand", true);
            s.html('展开 <i class="layui-icon layui-icon-down"></i>');
            q.find("[expand-show]").addClass("form-search-show-expand")
        }
        if (!t) {
            return
        }
        new Function("d", t)({expand: r, elem: s})
    });

    jquery(document).on("click.ew-sel-fixed", ".ew-select-fixed .layui-form-select .layui-select-title", function () {
        var w = jquery(this), s = w.parent().children("dl"), u = w.offset().top;
        var t = w.outerWidth(), y = w.outerHeight(), i = jquery(document).scrollTop();
        var v = s.outerWidth(), r = s.outerHeight();
        var x = u + y + 5 - i, q = w.offset().left;
        if (x + r > admin.getPageHeight()) {
            x = x - r - y - 10
        }
        if (q + v > admin.getPageWidth()) {
            q = q - v + t
        }
        s.css({"left": q, "top": x, "min-width": t})
    });

    admin.hideFixedEl = function () {
        jquery(".ew-select-fixed .layui-form-select").removeClass("layui-form-selected layui-form-selectup");
        jquery("body>.layui-laydate").remove()
    };

    jquery(document).on("click", ".layui-nav-tree>.layui-nav-item a", function () {
        var s = jquery(this), q = s.siblings(".layui-nav-child"), r = s.parent();
        if (q.length === 0) {
            return
        }
        if (r.hasClass("admin-nav-hover")) {
            return
        }
        if (r.hasClass("layui-nav-itemed")) {
            q.css("display", "none").slideDown("fast", function () {
                jquery(this).css("display", "")
            })
        } else {
            q.css("display", "block").slideUp("fast", function () {
                jquery(this).css("display", "")
            })
        }
        if (s.parents(".layui-nav").attr("lay-shrink") === "_all") {
            var i = s.parent().siblings(".layui-nav-itemed");
            i.children(".layui-nav-child").css("display", "block").slideUp("fast", function () {
                jquery(this).css("display", "")
            });
            i.removeClass("layui-nav-itemed")
        }
    });

    jquery('.layui-nav-tree[lay-shrink="all"]').attr("lay-shrink", "_all");
    jquery(document).on("click", ".layui-collapse>.layui-colla-item>.layui-colla-title", function () {
        var t = jquery(this), i = t.siblings(".layui-colla-content"), r = t.parent().parent(), q = i.hasClass("layui-show");
        if (q) {
            i.removeClass("layui-show").slideDown("fast").addClass("layui-show")
        } else {
            i.css("display", "block").slideUp("fast", function () {
                jquery(this).css("display", "")
            })
        }
        t.children(".layui-colla-icon").html("&#xe602;").css({
            "transition": "all .3s",
            "transform": "rotate(" + (q ? "90deg" : "0deg") + ")"
        });
        if (r.attr("lay-shrink") === "_all") {
            var s = r.children(".layui-colla-item").children(".layui-colla-content.layui-show").not(i);
            s.css("display", "block").slideUp("fast", function () {
                jquery(this).css("display", "")
            });
            s.removeClass("layui-show");
            s.siblings(".layui-colla-title").children(".layui-colla-icon").html("&#xe602;").css({
                "transition": "all .3s",
                "transform": "rotate(0deg)"
            })
        }
    });

    jquery(".layui-collapse[lay-accordion]").attr("lay-shrink", "_all").removeAttr("lay-accordion");

    layer.oldTips = layer.tips;
    layer.tips = function (s, i, r) {
        var q;
        if (jquery(i).length > 0 && jquery(i).parents(".layui-form").length > 0) {
            if (jquery(i).is("input") || jquery(i).is("textarea")) {
                q = jquery(i)
            } else {
                if (jquery(i).hasClass("layui-form-select") || jquery(i).hasClass("layui-form-radio") || jquery(i).hasClass("layui-form-checkbox") || jquery(i).hasClass("layui-form-switch")) {
                    q = jquery(i).prev()
                }
            }
        }
        if (!q) {
            return layer.oldTips(s, i, r)
        }
        r.tips = [q.attr("lay-direction") || 3, q.attr("lay-bg") || "#ff4c4c"];
        setTimeout(function () {
            r.success = function (t) {
                jquery(t).children(".layui-layer-content").css("padding", "6px 12px")
            };
            layer.oldTips(s, i, r)
        }, 100)
    };

    var tempData = admin.getTempData(true); // 本地永久存储
    if (tempData) {
        var configKeys = ["pageTabs", "cacheTab", "defaultTheme", "navArrow", "closeFooter", "tabAutoRefresh"];
        for (var i = 0; i < configKeys.length; i++) {
            if (tempData[configKeys[i]] !== undefined) {
                setter[configKeys[i]] = tempData[configKeys[i]] // 恢复配置
            }
        }
    }

    admin.recoverState(); // 恢复配置信息
    admin.renderTpl(); // 渲染动态模板

    exports("admin", admin)
});